package com.haust.community.service;

import com.haust.community.pojo.User;
import com.haust.community.utils.CommunityConstant;
import com.haust.community.utils.RedisKeyUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @Auther: csp1999
 * @Date: 2020/11/28/9:41
 * @Description: 关注Service 存入Redis 缓存
 */
@Service
public class FollowService implements CommunityConstant {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserService userService;

    /**
     * 用户关注了某个实体
     *
     * @param userId
     * @param entityType
     * @param entityId
     */
    public void follow(int userId, int entityType, int entityId) {
        redisTemplate.execute(new SessionCallback() {
            @Override
            public Object execute(RedisOperations operations) throws DataAccessException {
                // 某个用户所关注的实体的集合key
                String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType);
                // 某个实体拥有的粉丝集合key
                String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId);

                // 开启redis事务
                operations.multi();

                // 用户所关注的实体的集合新增一条关注数据
                operations.opsForZSet().add(followeeKey, entityId, System.currentTimeMillis());
                // 实体拥有的粉丝集合新增一个粉丝
                operations.opsForZSet().add(followerKey, userId, System.currentTimeMillis());

                // 执行redis事务
                return operations.exec();
            }
        });
    }

    /**
     * 用户取消关注了某个实体
     *
     * @param userId
     * @param entityType
     * @param entityId
     */
    public void unfollow(int userId, int entityType, int entityId) {
        redisTemplate.execute(new SessionCallback() {
            @Override
            public Object execute(RedisOperations operations) throws DataAccessException {
                // 某个用户所关注的实体的集合key
                String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType);
                // 某个实体拥有的粉丝集合key
                String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId);

                // 开启redis事务
                operations.multi();

                // 用户关注所关注的实体的集合减少一条关注数据
                operations.opsForZSet().remove(followeeKey, entityId);
                // 实体拥有的粉丝集合减少一个粉丝
                operations.opsForZSet().remove(followerKey, userId);

                // 执行redis事务
                return operations.exec();
            }
        });
    }

    /**
     * 查询关注的实体的数量
     *
     * @param userId
     * @param entityType
     * @return
     */
    public long findFolloweeCount(int userId, int entityType) {
        // 某个用户所关注的实体的集合key
        String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType);
        return redisTemplate.opsForZSet().zCard(followeeKey);
    }

    /**
     * 查询实体的粉丝的数量
     *
     * @param entityType
     * @param entityId
     * @return
     */
    public long findFollowerCount(int entityType, int entityId) {
        // 某个实体拥有的粉丝集合key
        String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId);
        return redisTemplate.opsForZSet().zCard(followerKey);
    }

    /**
     * 查询当前用户是否已关注该实体
     *
     * @param userId
     * @param entityType
     * @param entityId
     * @return
     */
    public boolean hasFollowed(int userId, int entityType, int entityId) {
        // 某个用户所关注的实体的集合key
        String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType);
        return redisTemplate.opsForZSet().score(followeeKey, entityId) != null;
    }

    /**
     * 查询某用户关注的人
     *
     * @param userId
     * @param offset
     * @param limit
     * @return
     */
    public List<Map<String, Object>> findFollowees(int userId, int offset, int limit) {
        // 某个用户所关注的用户集合key
        String followeeKey = RedisKeyUtil.getFolloweeKey(userId, ENTITY_TYPE_USER);

        // 分页
        Set<Integer> targetIds = redisTemplate.opsForZSet().reverseRange(followeeKey, offset, offset + limit - 1);

        // 判空
        if (targetIds == null) {
            return null;
        }

        // 结果拼接封装成list
        List<Map<String, Object>> list = new ArrayList<>();
        for (Integer targetId : targetIds) {
            Map<String, Object> map = new HashMap<>();
            User user = userService.findUserById(targetId);
            // 存入用户信息
            map.put("user", user);
            Double score = redisTemplate.opsForZSet().score(followeeKey, targetId);
            System.out.println(score+"=====================================================");
            // 存入时间(score中 存入的是日期毫秒数,Double类型)
            map.put("followTime", new Date(score.longValue()));
            list.add(map);
        }

        return list;
    }

    /**
     * 查询某用户的粉丝
     *
     * @param userId
     * @param offset
     * @param limit
     * @return
     */
    public List<Map<String, Object>> findFollowers(int userId, int offset, int limit) {

        // 某个实体拥有的粉丝集合key
        String followerKey = RedisKeyUtil.getFollowerKey(ENTITY_TYPE_USER, userId);

        // 分页
        Set<Integer> targetIds = redisTemplate.opsForZSet().reverseRange(followerKey, offset, offset + limit - 1);

        // 判空
        if (targetIds == null) {
            return null;
        }

        // 结果拼接封装成list
        List<Map<String, Object>> list = new ArrayList<>();
        for (Integer targetId : targetIds) {
            Map<String, Object> map = new HashMap<>();
            User user = userService.findUserById(targetId);
            map.put("user", user);
            Double score = redisTemplate.opsForZSet().score(followerKey, targetId);
            map.put("followTime", new Date(score.longValue()));
            list.add(map);
        }

        return list;
    }
}
